package network.httpserver;

import java.io.IOException;
import java.nio.BufferOverflowException;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.charset.Charset;

public class Response implements Sendable{

	static class Code{
		private int number;
		private String reason;
		private Code(int n, String r){number = n; reason = r;}
		public String toString() { return number + " " + reason;	}
		
		static Code OK = new Code(200, "OK");
		static Code BAD_REQUEST = new Code(400, "Bad Request");
		static Code NOT_FOUND = new Code(404, "Not Found");
		static Code METHOD_NOT_ALLOWED = new Code(405, "Method Not Allowed");
	}
	
	private Code code;
	private Content content;
	private boolean headersOnly;
	private ByteBuffer headerBuffer;
	
	private String CRLF = "\r\n";
	private Charset charset = Charset.forName("UTF-8");
	
	public Response(Code rc, Content c){
		this(rc, c, null);
	}
	
	public Response(Code rc, Content c, Request.Action ra) {
		code = rc;
		content = c;
		headersOnly = (ra == Request.Action.HEAD);
	}
	
	/*
	 * 创建HTTP请求头，存放到ByteBuffer中
	 */
	private ByteBuffer headers(){
		CharBuffer cb = CharBuffer.allocate(1024);
		for(;;){
			try{
				cb.put("HTTP/1.1 ").put(code.toString()).put(CRLF);
				cb.put("Server:nio/1.1").put(CRLF);
				cb.put("Content-type:").put(content.type()).put(CRLF);
				cb.put("Content-length:").put(Long.toString(content.length())).put(CRLF);
				cb.put(CRLF);
				break;
			}catch(BufferOverflowException e){
				cb = CharBuffer.allocate(cb.capacity() * 2);
				continue;
			}
		}
		cb.flip();
		return charset.encode(cb);
	}
	
	@Override
	public void prepare() throws IOException {
		content.prepare();
		headerBuffer = headers();
	}

	/*
	 * 发送HTTP相应，如果发送完毕返回false,否则返回true
	 * @see network.httpserver.Sendable#send(network.httpserver.ChannelIO)
	 */
	@Override
	public boolean send(ChannelIO cio) throws IOException {
		if(headerBuffer == null){
			throw new IllegalStateException();
		}
		
		//发送响应头
		if(headerBuffer.hasRemaining()){
			if(cio.write(headerBuffer) <= 0)
				return true;
		}
		//发送响应正文
		if(!headersOnly){
			if(content.send(cio))	return true;
		}
		return false;
	}

	@Override
	public void release() throws IOException {
		content.release();
	}

}
